//    Copyright (C) Clear Office.  All rights reserved.
using System;
using System.ComponentModel;

namespace Office.Spreadsheet
{
    internal class WeakEventHandler<T, TEventArgs> : IWeakEventHandler<TEventArgs>
        where T : class
        where TEventArgs : EventArgs
    {
        private readonly EventHandler<TEventArgs> _handler;
        private readonly OpenEventHandler _openHandler;
        private readonly WeakReference _target;
        private UnregisterCallback<TEventArgs> _unregister;

        public WeakEventHandler(EventHandler<TEventArgs> eventHandler, UnregisterCallback<TEventArgs> unregister)
        {
            _target = new WeakReference(eventHandler.Target);
            _openHandler = (OpenEventHandler) Delegate.CreateDelegate(typeof (OpenEventHandler),
                                                                      null, eventHandler.Method);
            _handler = invoke;
            _unregister = unregister;
        }

        #region IWeakEventHandler<TEventArgs> Members

        public EventHandler<TEventArgs> Handler
        {
            get { return _handler; }
        }

        #endregion

        private void invoke(object sender, TEventArgs eventArgs)
        {
            var target = (T) _target.Target;

            if (target != null)
                _openHandler(target, sender, eventArgs);
            else if (_unregister != null)
            {
                _unregister(_handler);
                _unregister = null;
            }
        }

        public static implicit operator EventHandler<TEventArgs>(WeakEventHandler<T, TEventArgs> weh)
        {
            return weh._handler;
        }

        #region Nested type: OpenEventHandler

        private delegate void OpenEventHandler(T @this, object sender, TEventArgs eventArgs);

        #endregion
    }
    interface IWeakPropertyChangedEventHandler
    {
        PropertyChangedEventHandler Handler { get; }
    }
    internal class WeakPropertyChangedEventHandler<T>: IWeakPropertyChangedEventHandler where T: class
        
    {
        private readonly PropertyChangedEventHandler _handler;
        private readonly OpenEventHandler _openHandler;
        private readonly WeakReference _target;
        private UnregisterPropertyChangedCallback _unregister;

        public WeakPropertyChangedEventHandler(PropertyChangedEventHandler eventHandler, UnregisterPropertyChangedCallback unregister)
        {
            _target = new WeakReference(eventHandler.Target);
            _openHandler = (OpenEventHandler)Delegate.CreateDelegate(typeof(OpenEventHandler),
                                                                      null, eventHandler.Method);
            _handler = invoke;
            _unregister = unregister;
        }

        #region IWeakEventHandler<TEventArgs> Members

        public PropertyChangedEventHandler Handler
        {
            get { return _handler; }
        }

        #endregion

        private void invoke(object sender, PropertyChangedEventArgs eventArgs)
        {
            var target = (T)_target.Target;

            if (target != null)
                _openHandler.Invoke(target, sender, eventArgs);
            else if (_unregister != null)
            {
                _unregister(_handler);
                _unregister = null;
            }
        }

        public static implicit operator PropertyChangedEventHandler(WeakPropertyChangedEventHandler<T>  weh)
        {
            return weh._handler;
        }

        #region Nested type: OpenEventHandler

        private delegate void OpenEventHandler(T @this, object sender, PropertyChangedEventArgs eventArgs);

        #endregion
    }

}